/**
 *
 */
#include <string>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>

// 引入自动生成的JNI头文件
#include "com_example_ndkjnidemo_home_staticregist_JNIMethodStatic.h"
// 引入日志工具类
#include "log-util.h"

int file_size2(const char *filename);

using namespace std;

//
static const char *const kClassJniTest = "com/example/ndkjnidemo/home/staticregist/JNIMethodStatic";
static const char *const kClassJniExtern = "com/example/ndkjnidemo/home/staticregist/ExternClass";

//保存java层的fieldID 和methodID 以方便后续使用
struct fields_t {
    jfieldID context;
    jfieldID name;
    jclass clazz;
    jobject obj;//obj的保存一定要使用NewGlobalRef的方法
    jmethodID setNameMethodID;
    jmethodID getNameMethodID;
    jmethodID transimFromJNIMethodID;
} fields;
struct fields_t *Pfield;

/**
 *
 */
extern "C" jstring JNICALL
Java_com_example_ndkjnidemo_home_staticregist_JNIMethodStatic_stringFromJNI(
        JNIEnv *env,
        jobject obj) {
    LOGI("JAVA 调用 JNI stringFromJNI");
    string hello = "Hello from JNI 静态注册";
    return env->NewStringUTF(hello.c_str());
}

/**
 *
 */
extern "C" void JNICALL Java_com_example_ndkjnidemo_home_staticregist_JNIMethodStatic_native_1init
        (JNIEnv *env, jobject object) {
    LOGI("JAVA 调用 JNI  native_1init");
    //初始化 方法 field id
    Pfield = &fields;
    jclass clazz = env->FindClass(kClassJniTest);
    Pfield->clazz = clazz;
    if (Pfield->clazz == NULL) {
        LOGE("can not find class");
        return;
    }

    Pfield->name = env->GetFieldID(clazz, "name", "Ljava/lang/String;");
    if (Pfield->name == NULL) {
        LOGE("can not find name ID");
        return;
    }

    Pfield->context = env->GetFieldID(clazz, "testContext", "Landroid/content/Context;");
    if (Pfield->context == NULL) {
        LOGE("can not find context ID");
        return;
    }

    Pfield->setNameMethodID = env->GetMethodID(
            clazz,
            "setName",
            "(Ljava/lang/String;)V");
    if (Pfield->setNameMethodID == NULL) {
        LOGE("can not find setNameMethodID");
        return;
    }

    Pfield->getNameMethodID = env->GetMethodID(
            clazz,
            "getName",
            "()Ljava/lang/String;");

    if (Pfield->getNameMethodID == NULL) {
        LOGE("can not find getNameMethodID");
        return;
    }

    Pfield->transimFromJNIMethodID = env->GetMethodID(
            clazz,
            "transimFromJNI",
            "(Ljava/lang/String;Lcom/example/ndkjnidemo/home/staticregist/ExternClass;)Ljava/lang/String;");

    if (Pfield->transimFromJNIMethodID == NULL) {
        LOGE("can not find transimFromJNIMethodID");
        return;
    }
}

/**
 *
 */
extern "C" void JNICALL Java_com_example_ndkjnidemo_home_staticregist_JNIMethodStatic_transmitToJNI
        (JNIEnv *env, jobject thizz, jstring information, jobject obj) {
    const char *transmitString = env->GetStringUTFChars(information, NULL);
    LOGI("JAVA 调用 JNI transmitToJNI transmitString=%s", transmitString);
    Pfield->obj = env->NewGlobalRef(thizz);//想持久保存thizz的对象，一定要使用NewGlobalRef 后续也要手动删除
    //初始化  field id 获取obj 的name
    jclass clazz = env->FindClass(kClassJniExtern);
    jfieldID fieldNameID = env->GetFieldID(clazz, "className", "Ljava/lang/String;");
    if (fieldNameID == NULL) {
        LOGE("can not find className ");
        return;
    }

    jobject objName;
    objName = env->GetObjectField(obj, fieldNameID);
    jstring jstringName = (jstring) (objName);
    const char *charName = env->GetStringUTFChars(jstringName, NULL);
    LOGI("JNI 调用 JAVA  ExternClass className=%s", charName);

    //调用java 层的方法。CallVoidMethod CallObjectMethod
    string message = "JNI 调用 JAVA ";
    jstring jMessage = env->NewStringUTF(message.c_str());
    env->CallVoidMethod(Pfield->obj, Pfield->setNameMethodID, jMessage);

    jobject callName = env->CallObjectMethod(Pfield->obj, Pfield->getNameMethodID);
    const char *callNameChar = env->GetStringUTFChars((jstring) callName, NULL);
    LOGI("JNI 调用 JAVA  getName=%s", callNameChar);
    jobject calltransim = env->CallObjectMethod(Pfield->obj, Pfield->transimFromJNIMethodID,
                                                jMessage, obj);

    const char *calltransimChar = env->GetStringUTFChars((jstring) calltransim, NULL);
    LOGI("JNI 调用 JAVA transimFromJNI calltransimChar=%s", calltransimChar);

    //垃圾回收
    env->DeleteLocalRef(callName);
    env->DeleteLocalRef(calltransim);
    env->DeleteLocalRef(objName);
    env->DeleteGlobalRef(Pfield->obj);
}
